package com.gh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gh.bo.TransFlowBO;
import com.gh.common.exception.Assert;
import com.gh.common.exception.BusinessException;
import com.gh.common.result.ResponseEnum;
import com.gh.entity.UserAccount;
import com.gh.entity.UserInfo;
import com.gh.enums.TransTypeEnum;
import com.gh.hfb.FormHelper;
import com.gh.hfb.HfbConst;
import com.gh.hfb.RequestHelper;
import com.gh.mapper.TransFlowMapper;
import com.gh.mapper.UserAccountMapper;
import com.gh.mapper.UserInfoMapper;
import com.gh.service.TransFlowService;
import com.gh.service.UserAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gh.util.LendNoUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 用户账户 服务实现类
 * </p>
 *
 * @author Eric
 * @since 2021-09-06
 */
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Override
    public String commitCharge(BigDecimal chargeAmt, Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("agentId", HfbConst.AGENT_ID);
        map.put("agentBillNo", LendNoUtils.getChargeNo());
        UserInfo userInfo = userInfoMapper.selectById(userId);
        String bindCode = userInfo.getBindCode();
        if (StringUtils.isEmpty(bindCode)) {
            throw new BusinessException(ResponseEnum.USER_NO_BIND_ERROR);
        }
        map.put("bindCode", bindCode);
        map.put("chargeAmt", chargeAmt);
        map.put("feeAmt", 0);
        map.put("returnUrl", HfbConst.RECHARGE_RETURN_URL);
        map.put("notifyUrl", HfbConst.RECHARGE_NOTIFY_URL);
        map.put("timestamp", RequestHelper.getTimestamp());
        map.put("sign", RequestHelper.getSign(map));
        //动态生成表单字符串
        String formStr = FormHelper.buildForm(HfbConst.RECHARGE_URL, map);
        return formStr;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String notifyCharge(Map<String, Object> paramMap) {
        String agentBillNo = (String) paramMap.get("agentBillNo");
        //幂等性判断  判断交易流水号是否存在
        boolean isSave = transFlowService.isSaveTransFlow(agentBillNo);
        if (isSave) {
            return "success"; //幂等性返回
        }
        //账户处理
        String bindCode = (String) paramMap.get("bindCode");
        String chargeAmt = (String) paramMap.get("chargeAmt");
        baseMapper.updateAccount(bindCode, new BigDecimal(chargeAmt), new BigDecimal(0));
        //记录账户流水
        TransFlowBO transFlowBO = new TransFlowBO(agentBillNo, bindCode, new BigDecimal(chargeAmt), TransTypeEnum.RECHARGE, "充值啦");
        transFlowService.saveTransFlow(transFlowBO);
        return "success";
    }

    @Override
    public BigDecimal getAccount(Long userId) {
        LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserAccount::getUserId, userId);
        //查询账户信息
        UserAccount userAccount = userAccountMapper.selectOne(queryWrapper);
        return userAccount.getAmount();
    }

    @Override
    public String commitWithdraw(BigDecimal fetchAmt, Long userId) {
        BigDecimal account = this.getAccount(userId);//用户账户余额
        //判断账户余额是否充足
        Assert.isTrue(account.doubleValue() >= fetchAmt.doubleValue(), ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);
        Map<String, Object> map = new HashMap<>();
        map.put("agentId", HfbConst.AGENT_ID);
        map.put("agentBillNo", LendNoUtils.getWithdrawNo());
        UserInfo userInfo = userInfoMapper.selectById(userId);
        String bindCode = userInfo.getBindCode();
        if (StringUtils.isEmpty(bindCode)) {
            throw new BusinessException(ResponseEnum.USER_NO_BIND_ERROR);
        }
        map.put("bindCode", bindCode);
        map.put("fetchAmt", fetchAmt);
        map.put("feeAmt", new BigDecimal(0));
        map.put("returnUrl", HfbConst.WITHDRAW_RETURN_URL);
        map.put("notifyUrl", HfbConst.WITHDRAW_NOTIFY_URL);
        map.put("timestamp", RequestHelper.getTimestamp());
        map.put("sign", RequestHelper.getSign(map));
        //动态生成表单字符串
        String formStr = FormHelper.buildForm(HfbConst.WITHDRAW_URL, map);
        return formStr;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String notifyWithdraw(Map<String, Object> paramMap) {
        String agentBillNo = (String) paramMap.get("agentBillNo");
        //幂等性判断  判断交易流水号是否存在
        boolean isSave = transFlowService.isSaveTransFlow(agentBillNo);
        if (isSave) {
            return "success"; //幂等性返回
        }
        //账户处理
        String bindCode = (String) paramMap.get("bindCode");
        String fetchAmt = (String) paramMap.get("fetchAmt");
        baseMapper.updateAccount(bindCode, new BigDecimal(fetchAmt).negate(), new BigDecimal(0));
        //记录账户流水
        TransFlowBO transFlowBO = new TransFlowBO(agentBillNo, bindCode, new BigDecimal(fetchAmt), TransTypeEnum.WITHDRAW, "提现啦");
        transFlowService.saveTransFlow(transFlowBO);
        return "success";
    }
}
